﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using haptic.src.engine;
using Microsoft.Xna.Framework;
using haptic.src.engine.core;

namespace haptic.src.components
{
    [Serializable]
    public class cCharacter : Component
    {
        public enum State
        {
            E_IDLE = 0,
            E_RUN,
            E_JUMP,
            E_FALLING,
        }
        public enum Order
        {
            E_IDLE = 0,
            E_RUN,
            E_JUMP
        }
        public cCharacter(){}
        public cCharacter(Entity oOwner) : base(oOwner) { }

        #region Load
        public override Result Load(haptic.src.engine.Scene oGame, Microsoft.Xna.Framework.Content.ContentManager oContent)
        {
            m_oPhysics = (cPhysics)m_oEntity.GetComponent("cPhysics");
            if (m_oPhysics != null)
            {
                m_oPhysics.m_fRestitution = 0.0f;
            }
            return base.Load(oGame, oContent);
        }
        public override Result PostLoad(haptic.src.engine.Scene oGame)
        {
            m_oAutomate = (cAutomate)m_oEntity.GetComponent("cAutomate");
            return base.PostLoad(oGame);
        }
        #endregion

        #region Update
        public override void Update(GameTime oTime)
        {
            if (m_oAutomate == null)
                return;

            float fDt = (float)oTime.ElapsedGameTime.TotalSeconds;
            
            if (m_oPhysics != null)
            {
                // Facing direction
                if (Math.Abs(m_oPhysics.m_vVelocity.X) > 0.1f)
                {
                    if (m_oPhysics.m_vVelocity.X > 0.0f)
                        m_oAutomate.SetFacingDirection(Vector2.UnitX);
                    else
                        m_oAutomate.SetFacingDirection(-Vector2.UnitX);
                }

                if (m_oPhysics.bIsOnGround)
                {
                    if (Math.Abs(m_oPhysics.m_vVelocity.X) > m_fMinimumVelocityWhenColliding)
                    {
                        m_eState = State.E_RUN;
                    }
                    else
                    {
                        m_oPhysics.m_vVelocity.X = 0.0f;
                        m_eState = State.E_IDLE;
                    }
                    if (m_eOrder == Order.E_RUN)
                        m_oAutomate.m_oAutomateInstance.ChangeState("run");
                    else
                        m_oAutomate.m_oAutomateInstance.ChangeState("idle");
                }
                else
                {
                    if (m_oPhysics.m_vVelocity.Y > m_fMinimumVelocityForFalling)
                    {
                        m_eState = State.E_FALLING;
                        m_oAutomate.m_oAutomateInstance.ChangeState("fall");
                    }
                    else if (m_oPhysics.m_vVelocity.Y < 0.0f)
                    {
                        m_eState = State.E_JUMP;
                        m_oAutomate.m_oAutomateInstance.ChangeState("jump");
                    }
                }
            }
        }
        public override void PostUpdate(GameTime oTime)
        {
            base.PostUpdate(oTime);
        }
        #endregion

        #region Actions
        public void SetOrder(Order eOrder)
        {
            Debug.Assert(m_oPhysics != null);
            switch(eOrder)
            {
                case Order.E_IDLE:
                    break;
                case Order.E_JUMP:
                    m_eState = State.E_JUMP;
                    m_oPhysics.m_vVelocity.Y -= m_fJumpVerticalImpulse;
                    break;
                case Order.E_RUN:
                    break;
            }
            m_eOrder = eOrder;
        }
        #endregion

        #region Draw
        #endregion

        #region Attributes
        protected float m_fJumpVerticalImpulse = 800.0f;
        protected float m_fMinimumVelocityWhenColliding = 4.0f;
        protected float m_fMinimumVelocityForFalling = 200.0f;
        protected cPhysics m_oPhysics;
        protected State m_eState = State.E_IDLE;
        protected cAutomate m_oAutomate;
        protected Order m_eOrder = Order.E_IDLE;
        #endregion
    }
}
